package com.etung.iot.demo.storage.conTriggerStorage;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.etung.iot.demo.dao.ConditionStorageMapper;
import com.etung.iot.demo.dao.RealDataMapper;
import com.etung.iot.demo.modles.ConditionStorageEntity;
import com.etung.iot.demo.modles.MyPair;
import com.etung.iot.demo.modles.RealData;
import com.etung.iot.demo.storage.constorage.TargetTypeEnum;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import javafx.util.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

@Component
public class PreConditionStorageUtil {
    @Autowired
    private ConditionStorageMapper conditionStorageMapper;
    @Autowired
    private RealDataMapper realDataMapper;

    private static final String CONDITION_CACHE_PREFIX = "precondition:";

    //生产环境请使用redis
    private static Map<String, List<ConditionStorageEntity>> storageMap = Maps.newConcurrentMap();
    //上次存储时间
    private static Map<String, Long> lastStoreMap = Maps.newConcurrentMap();

    //变化存储
    private static List<ConditionStorageEntity> changeTypeList = Lists.newCopyOnWriteArrayList();
    //变化存储的上次存储
    private static Map<String, MyPair<RealData>> changeLastStoreMap = Maps.newConcurrentMap();

    /**
     * @param imei
     * @param
     * @return
     */
    public List<ConditionStorageEntity> getConditionStorageRule(String imei, Integer monitorVarId) {
        String key = imei + "_" + monitorVarId;
        if (!storageMap.containsKey(key)) {
            List<ConditionStorageEntity> conditionStorageEntityList = conditionStorageMapper.selectList(new QueryWrapper<ConditionStorageEntity>().eq("imei", imei).eq("monitor_id", monitorVarId));
            if (conditionStorageEntityList != null && conditionStorageEntityList.size() > 0) {
                storageMap.put(key, conditionStorageEntityList);
                return conditionStorageEntityList;
            }
        } else {
            return storageMap.get(key);
        }
        return Lists.newArrayList();
    }

    public void loadChangeTypeList() {
        changeTypeList.clear();
        List<ConditionStorageEntity> conditionStorageEntityList = conditionStorageMapper.selectList(null);
        if (conditionStorageEntityList != null && conditionStorageEntityList.size() > 0) {
            for (ConditionStorageEntity entity : conditionStorageEntityList) {
                if (entity.getTargetType() == TargetTypeEnum.CHANGE_TYPE.getValue()) {
                    changeTypeList.add(entity);
                }
            }
        }

    }

    public boolean isIncludeChangeConStorage(String imei, Integer monitorVarId) {
        if (changeTypeList.size() == 0) return false;
        for (ConditionStorageEntity entity : changeTypeList) {
            if (entity.getImei().equals(imei) && entity.getMonitorId().intValue() == monitorVarId) {
                return true;
            }
        }
        return false;
    }

    public void removeConditionStorageRule(String imei) {
        storageMap.entrySet().removeIf(entry -> entry.getKey().startsWith(imei));
        lastStoreMap.entrySet().removeIf(entry -> entry.getKey().startsWith(imei));
        changeTypeList.clear();
    }

    public Long getLastStoreTimestamp(String imei, Integer varId) {
        String key = CONDITION_CACHE_PREFIX + imei + "_" + varId;
        Long res = 0L;
        if (lastStoreMap.containsKey(key)) {
            res = lastStoreMap.get(key);
        } else {
            RealData realData = realDataMapper.selectOne(
                    new QueryWrapper<RealData>()
                            .eq("imei", imei).eq("variant_id", varId)
                            .orderByDesc("`time`").last("limit 1")

            );
            if (realData != null) {
                res = realData.getTime().getTime();
                lastStoreMap.put(key, res);
            }
        }
        return res;
    }

    public void saveLastStoreTimestamp(String imei, Integer varId, Long timestamp) {
        String key = CONDITION_CACHE_PREFIX + imei + "_" + varId;
        lastStoreMap.put(key, timestamp);
    }

    /**
     * 保存上次变化的监控变量
     *
     * @param imei
     * @param realData
     */
    public void saveChangeTypeLastRealData(String imei, RealData realData) {
        Integer varId = realData.getVarId();
        String key = imei + "_" + varId;
        MyPair<RealData> realDataPair = changeLastStoreMap.get(key);
        if (realDataPair == null) {
            //先从数据库加载上一次的变量值
            RealData lastRealData = realDataMapper.selectOne(
                    new QueryWrapper<RealData>()
                            .eq("imei", imei).eq("variant_id", varId)
                            .orderByDesc("`time`").last("limit 1")

            );
            realDataPair = new MyPair<>();
            if(lastRealData != null) realDataPair.put(lastRealData);
            realDataPair.put(realData);
            changeLastStoreMap.put(key, realDataPair);
        } else {
            realDataPair.put(realData);
        }
    }

    /**
     * 取出上次的监控变量值
     *
     * @param imei
     * @return
     */
    public RealData getChangeTypeLastRealData(String imei, Integer varId) {
        String key = imei + "_" + varId;
        MyPair<RealData> realDataMyPair = changeLastStoreMap.get(key);
        if (realDataMyPair == null) return null;
        return realDataMyPair.getLastData();
    }
}
